package structures.xmltable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.event.ValueChangeEvent;

import structures.ValuePair;

import manager.KysManager;
import manager.LoadNativeTableManager;
import manager.SessionManager;

import analyzers.ExposedAnalyzer;
import analyzers.GridAnalyzer;

import constants.EnvironmentConstants;
import constants.Globals;
import domain.DadServiceParametersDAO;
import domain.DdBagkeysDAO;
import exception.IBToolsException;


@SuppressWarnings("serial")
public class ServiceBaseTypeParameter implements Serializable, Globals{
	
	private static final String DOCUMENTID = "DOCUMENTID";
	
	protected int bagIndex;

	protected String bagKey;
	protected String value;
	protected String aciklama;

	protected String idValue;
	
	protected boolean optional;
	protected boolean active;
	protected boolean input;
	protected boolean yeni;
	
	protected String type;
	
	protected boolean kysAnalyzed;
	protected boolean kysDefined;

	protected boolean unallowedInDebugCall;
	
	protected boolean updating;

	protected ServiceParameterTable imposedTable;
	protected boolean bagGridVisible;
	
	protected long dbParameterOid;

//	protected List<String> possibleValues;
	
	protected List<ValuePair> valuePairs;

	public ServiceBaseTypeParameter(boolean input, String type) {
		super();
		initNew();
		this.input = input;
		this.type = type.trim();
	}
	
	public ServiceBaseTypeParameter(String bagKey, String value,
			String aciklama, boolean optional,
			boolean input, String type, boolean kysDefined) {
		super();
		init(bagKey, value, aciklama, optional, input, type);
		definedToKys(kysDefined);
	}
	
	public ServiceBaseTypeParameter(DadServiceParametersDAO dadServiceParametersDAO, boolean kysDefined) throws IBToolsException {
		super();
		initFromDBParameter(dadServiceParametersDAO);
		definedToKys(kysDefined);
	}
	
	public ServiceBaseTypeParameter(String bagKey, String value,
			String aciklama, boolean optional,
			boolean input, String type) {
		super();
		init(bagKey, value, aciklama, optional, input, type);
	}

	ServiceBaseTypeParameter(String bagKey, String value) {
		super();
		initNew();
		setBagKey(bagKey);
		
		this.setValue(value);
	}
	
	ServiceBaseTypeParameter(String bagKey, String value,
			String aciklama, boolean optional,
			boolean input, boolean table, String type, boolean kysDefined) {
		super();
		init(bagKey, value, aciklama, optional, input,  type);
		definedToKys(kysDefined);
	}

	ServiceBaseTypeParameter(ServiceBaseTypeParameter param) {
		super();
		init(param.bagIndex, param.bagKey, param.value, param.aciklama, param.optional, param.active, param.input, param.yeni, param.type);
	}

	ServiceBaseTypeParameter(int bagIndex, String bagKey, String value,
			String aciklama, boolean optional, boolean active,
			boolean input, boolean yeni, String type) {
		super();
		init(bagIndex, bagKey, value, aciklama, optional, active, input, yeni, type);
	}

	ServiceBaseTypeParameter(boolean input, boolean table) {
		super();
		initNew();
		this.input = input;
	}

	private void init(int bagIndex, String bagKey, String value,
			String aciklama, boolean optional, boolean active,
			boolean input, boolean yeni, String type){

		this.bagIndex = bagIndex;
		setBagKey(bagKey);
		this.setValue(value);
		this.aciklama = aciklama;
		this.optional = optional;
		this.active = active;
		this.input = input;
		this.yeni = yeni;
		this.type = type.trim();
	}
	
	private void initNew(){
		this.bagIndex = 0;
		setBagKey(Globals.EMPTY_STRING);
		this.value = Globals.EMPTY_STRING;
		this.aciklama = Globals.EMPTY_STRING;
		this.optional = true;
		this.active = true;
		this.input = true;
		this.yeni = true;
		this.type = PARAM_STRING;
	}	
	private void init(String bagKey, String value,
			String aciklama, boolean optional,
			boolean input, String type){
		initNew();
		setBagKey(bagKey);
		this.setValue(value);
		this.aciklama = aciklama;
		this.optional = optional;
		this.input = input;
		this.yeni = false;
		this.type = type.trim();
	}
	public void initFromDBParameter(DadServiceParametersDAO dbParameter) throws IBToolsException{
		this.setBagKey(dbParameter.getName());
		if(this.getValue() == null)
			this.setValue(Globals.EMPTY_STRING);
		this.setAciklama(dbParameter.getDescription());
		this.setOptional(dbParameter.getOptional().equals(TRUE_CHAR));
		this.setInput(dbParameter.getIoType().equals(IOTYPE_INPUT));
		this.setType(dbParameter.getType());
		definedToKys(true);
		this.dbParameterOid = dbParameter.getOid();
		fillPossibleValues();
	}

	public void initFromDB(long serviceOid) throws IBToolsException{
		DadServiceParametersDAO dbParameter = KysManager.loadKYSParameter(this.bagKey, serviceOid);
		if(dbParameter != null){
			initFromDBParameter(dbParameter);
		}
		else{
			definedToKys(false);
		}
	}
	
	public String getRowClass(){
		String rowClass = "";
		if(!isInput()){
			rowClass = "param_output";
		}
		else if(unallowedInDebugCall){
			rowClass = "unallowed-debug-row";
		}
		else if(kysAnalyzed){
			if(kysDefined){
				if(isOptional()){
					rowClass = "even-row";
				}
				else {
					rowClass = "must-param-row";
				}
			}
			else {
				rowClass = "kys-undefined-param-row";
			}
		}
		else {
			rowClass = "even-row";
		}
		return rowClass;
	}

	public String getBagKey() {
		return bagKey;
	}

	public void setBagKey(String bagKey) {
		if(bagKey != null)
			this.bagKey = bagKey.toUpperCase();
		else
			this.bagKey = bagKey;
	}

	public DdBagkeysDAO getBagKeyDAO() {
		return new DdBagkeysDAO(bagKey);
	}

	public void setBagKeyDAO(DdBagkeysDAO bagKeyDAO) {
		if(bagKeyDAO == null)
			setBagKey(EMPTY_STRING);
		else
			setBagKey(bagKeyDAO.getBagkeyname());
	}

	public String getValue() {
		return value;
	}

	public ValuePair getPossibleValue() {
		return new ValuePair(value, "");
	}

	public void setPossibleValue(ValuePair valuePair) {
		if(valuePair != null)
			value = valuePair.getValue();
	}
	
	public void setValue(String value) {
		this.value = value;
	}
	
	public void analyzeValue() throws IBToolsException{
		if(type.equalsIgnoreCase(PARAM_BAG) && !ExposedAnalyzer.isExposedString(this.value)){
			value = value.concat("~");
		}
		if(bagGridVisible && isImposed()){
			if(ExposedAnalyzer.isExposedString(this.value)){
				fillImposedTable();
			}
			else if(this.value.startsWith("PROCESS")){
				fillGridTable();
			}
		}
		fillPossibleValues();
	}

	public boolean isOptional() {
		return optional;
	}

	public void setOptional(boolean optional) {
		this.optional = optional;
	}

	public String getAciklama() {
		return aciklama;
	}
	public String getTooltip() {
		String tooltip = type;
		if(aciklama != null && !aciklama.equals(EMPTY_STRING)){
			tooltip = aciklama + " - " + tooltip;
		}
		return tooltip;
	}

	public void setAciklama(String aciklama) {
		this.aciklama = aciklama;
	}

	public boolean isInputText(){
		boolean sonuc =input 
				&& !isTable() 
//				&& !type.equals(PARAM_INT) 
//				&& !type.equals(PARAM_LONG) 
//				&& !type.equals(PARAM_CURRENCY) 
				&& !type.trim().equals(PARAM_DATE) 
				&& !type.trim().equals(PARAM_BOOLEAN)
				&& !isImposedAndVisible()
				;
		return sonuc;
	}
	public boolean isOutputText(){
		return !isTable()
				&& !isDocument() 
				&& !isImposedAndVisible();
	}
	public boolean isInputString(){
		return input && !isTable() && (type.trim().equals(PARAM_STRING) || type.trim().equals(PARAM_BAG));
	}
	public boolean isInputInt(){
		return input && !isTable() && type.trim().equals(PARAM_INT);
	}
	public boolean isInputLong(){
		return input && !isTable() && type.trim().equals(PARAM_LONG);
	}
	public boolean isInputCurrency(){
		return input && !isTable() && type.trim().equals(PARAM_CURRENCY);
	}
	public boolean isInputNumeric(){
		return isInputInt() || isInputLong();
	}
	public boolean isInputDate(){
		return input && !isTable() && type.trim().equals(PARAM_DATE);
	}
	public boolean isInputBoolean(){
		return input && !isTable() && type.trim().equals(PARAM_BOOLEAN);
	}
	public boolean isInputTable(){
		return input && isTable();
	}

	public void fillImposedTable() throws IBToolsException{
		imposedTable = ExposedAnalyzer.analyze(null, value);
	}

	public void fillGridTable() throws IBToolsException{
		imposedTable = GridAnalyzer.toughAnalyze(value);
	}

	public void fillPossibleValues() throws IBToolsException{
		if(this.aciklama != null && this.aciklama.indexOf("P(") > -1){
			try {
				int startOfTable = aciklama.indexOf("P(") + 2;
				int endOfTable = aciklama.indexOf(")P");
				String tableName = aciklama.substring(startOfTable, endOfTable);
				int startOfColumn = aciklama.indexOf("C(") + 2;
				int endOfColumn = aciklama.indexOf(")C");
				String[] valueLabelColumn = aciklama.substring(startOfColumn, endOfColumn).split(",");
				String label = valueLabelColumn.length > 1 ? valueLabelColumn[1] : "";
				valuePairs = LoadNativeTableManager.loadPossibleValuePairs(tableName, valueLabelColumn[0], label);
			} catch (Exception e) {
				
			}
		}
		else if(this.aciklama != null && this.aciklama.indexOf("S(") > -1){
			int startOfType = aciklama.indexOf("S(") + 2;
			int endOfType = aciklama.indexOf(")S");
			String[] types = aciklama.substring(startOfType, endOfType).split(",");
			valuePairs = new ArrayList<ValuePair>();
			for (String type : types) {
				String[] pairs = type.split("-");
				if(pairs.length > 1)
					valuePairs.add(new ValuePair(pairs[0], pairs[1]));
				else
					valuePairs.add(new ValuePair(pairs[0], "No Description"));
			}
		}
		else {
			if(valuePairs != null)
				valuePairs = null;
		}
	}
	
	public boolean isUserBagkey(){
		boolean sonuc = false;
		if(bagKey.indexOf("KULLANICIKOD") > -1 || bagKey.indexOf("USERCOD") > -1){
			sonuc = true;
		}
		return sonuc;
	}
	
	public String toString(){
		return this.bagKey;
	}

	public boolean isInput() {
		return input;
	}

	public void setInput(boolean input) {
		this.input = input;
	}

	public boolean isActive() {
		return active;
	}

	public void setActive(boolean active) {
		this.active = active;
	}
	public ServiceBaseTypeParameter clone(){
		ServiceBaseTypeParameter clone = new ServiceBaseTypeParameter(
				bagIndex, bagKey, value, aciklama, optional, active, input, yeni, type);
		return clone;
	}
	
	public ServiceBaseTypeParameter shallowClone(){
		ServiceBaseTypeParameter clone = new ServiceBaseTypeParameter(bagKey, value);
		clone.setType(type);
		clone.setInput(input);
		
		return clone;
	}
	
	public void cloneTo(ServiceBaseTypeParameter targetTable){
		if(targetTable == null){
			targetTable = clone();
		}
		else {
			targetTable.init(bagIndex, bagKey, value, aciklama, optional, active, input, yeni, type);
		}
	}

	public int getBagIndex() {
		return bagIndex;
	}

	public void setBagIndex(int bagIndex) {
		this.bagIndex = bagIndex;
	}

	public boolean isTable() {
		return type.trim().equalsIgnoreCase(PARAM_TABLE);
	}

	public boolean isYeni() {
		return yeni;
	}

	public void setYeni(boolean yeni) {
		this.yeni = yeni;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type.trim();
	}
	public String getVisualType() {
		return getVisualTypeFromType(type);
	}
	private static String getVisualTypeFromType(String type){
    	switch(type){
	    	case PARAM_STRING:
	    		return "String";
	    	case PARAM_BAG:
	    		return "Bag";
	    	case PARAM_INT:
	    		return "Int";
	    	case PARAM_LONG:
	    		return "Long";
	    	case PARAM_DATE:
	    		return "Date";
	    	case PARAM_CURRENCY:
	    		return "Amount";
	    	case PARAM_TABLE:
	    		return "Table";
	    	default:
	    		return "String";
    	}
	}

	public void definedToKys(boolean kysDefined) {
		this.kysDefined = kysDefined;
		if(kysDefined){
			kysAnalyzed = true;
		}
		else{
			undefineFromKYS();
		}
	}
	private void undefineFromKYS(){
		this.dbParameterOid = -1L;
		undefineChildrenFromKYS();
	}
	protected void undefineChildrenFromKYS(){
	}

	public boolean isKysDefined() {
		return kysDefined;
	}
	public void analayzedFromKys(boolean kysDefined) {
		this.kysAnalyzed = kysDefined;
	}
	
	public boolean isKysAnalyzed() {
		return kysAnalyzed;
	}
	public void analyzeType(){
		if(bagKey != null){
			if(bagKey.indexOf("TARIH") > -1 || bagKey.indexOf("DATE") > -1)
				type = PARAM_DATE;
			if(bagKey.indexOf("BAG") > -1)
				type = PARAM_BAG;
			else if(bagKey.indexOf("OID") > -1)
				type = PARAM_LONG;
			else if(bagKey.indexOf("MUSTERINO") > -1 || bagKey.indexOf("CUSTOMERNO") > -1)
				type = PARAM_INT;
		}
	}
	private String documentLink;
	public void checkDocumentOidStatus(Integer environment){
		if(isDocument()){
			createDocumentLink(environment);
		}
	}
	public void createDocumentLink(Integer environment){
		documentLink = "http://" + EnvironmentConstants.ENVIR_PRINTSERVER.get(environment) + 
				"/CBReportTransmitServlet?user=RPA&type=WEB&docid=" + value + "&port=3333";
	}
	public String getDocumentLink(){
		return documentLink;
	}
	public boolean isDocument(){
		return bagKey.indexOf(DOCUMENTID) > -1;
	}
	public boolean isBooleanValue() {
		boolean sonuc = false;
		if(value != null)
			sonuc = value.trim().equals(TRUE_STRING) || value.trim().equals(TRUE_WORD);
		return sonuc;
	}

	public void setBooleanValue(String booleanValue) {
		value = booleanValue;
		
	}
	
	public void booleanChange(ValueChangeEvent event) {
		boolean booleanValue = Boolean.valueOf(event.getNewValue().toString()).booleanValue();
		value = booleanValue ? TRUE_STRING : FALSE_STRING;
	}
	
	public void setBooleanValue(boolean booleanValue) {
		value = booleanValue ? TRUE_STRING : FALSE_STRING;
		
	}

	public boolean isUnallowedInDebugCall() {
		return unallowedInDebugCall;
	}

	public void setUnallowedInDebugCall(boolean unallowedInDebugCall) {
		this.unallowedInDebugCall = unallowedInDebugCall;
	}

	public boolean isUpdating() {
		return updating;
	}

	public void setUpdating(boolean updating) {
		this.updating = updating;
	}

	public boolean isImposed() {
		return ExposedAnalyzer.isExposedString(this.value) || this.value.startsWith("PROCESS") || this.type.equalsIgnoreCase(PARAM_BAG);
	}
	
	public boolean isImposedAndVisible() {
		return isImposed() && isBagGridVisible();
	}

	public void setImposed(boolean imposed) {
	}

	public ServiceParameterTable getImposedTable() {
		return imposedTable;
	}

	public void setImposedTable(ServiceParameterTable imposedTable) {
		this.imposedTable = imposedTable;
	}
	
	public void toggleBagGridVisible() throws IBToolsException{
		bagGridVisible = !bagGridVisible;
		if(bagGridVisible){
			analyzeValue();
		}
	}

	public Integer getOutTextLineHeight(){
		Integer sonuc = ((value.length() / 35) + 1) * 16;
		if(isImposed() && sonuc < 25){
			sonuc = 25;
		}
		return sonuc;
	}
	
	public String getExtraStyleClass(){
		StringBuffer response = new StringBuffer();
		if(bagKey.equalsIgnoreCase("COOKIE")) 
			response.append("diagonal-light-blue ");
		else if(bagKey.equalsIgnoreCase("SESSION_ID")) 
			response.append("diagonal-light-blue ");
		else if(bagKey.equalsIgnoreCase("INFO_MESSAGE_TEXT")) 
			response.append("info-outrow ");
		return response.toString();
	}
	
	public boolean isPossibleValuesAvailable(){
		return valuePairs != null && valuePairs.size() > 0;
	}

	public List<ValuePair> getPossibleValuePairs() {
		if(valuePairs == null)
			valuePairs = new ArrayList<ValuePair>();
		return valuePairs;
	}

	public void setPossibleValuePairs(List<ValuePair> valuePairs) {
		this.valuePairs = valuePairs;
	}

	public long getDbParameterOid() {
		return dbParameterOid;
	}
	
	public void setDbParameterOid(Long dbParameterOid) {
		if(dbParameterOid == null)
			dbParameterOid = 0L;
		this.dbParameterOid = dbParameterOid;
	}
	public boolean isLoginUserDefinedInKYS(){
		return SessionManager.isAdminUser() || (aciklama != null && aciklama.indexOf(SessionManager.getLoginUserCode()) > -1);
	}

	public String getIdValue() {return null;}
	public void setIdValue(String idValue) {}

	public boolean isBagGridVisible() {
		return bagGridVisible;
	}

	public void setBagGridVisible(boolean bagGridVisible) {
		this.bagGridVisible = bagGridVisible;
	}
}
